# 完成本周1.18的阶段案例《飞机大战》游戏中没有完成的部分
# 1）完成敌机发射子弹功能（注意：子弹不是连发、移动速度不要太快）
# 2）实现敌机子弹和玩家飞机的碰撞检测
# 3）为消失的飞机添加爆炸效果
# 第二周作业4
# 班级：Python五期
# 学员：李子坚

# 导入相应的 模块
import pygame
from pygame.locals import *
import time,random                       

class Bullet:
    '''子弹类'''
    def __init__(self, screen_temp, x, y):
        self.x = x + 53
        self.y = y
        self.screen = screen_temp
        self.image = pygame.image.load("./images/pd.png")

    def display(self):
        '''绘制子弹'''
        self.screen.blit(self.image,(self.x,self.y))

    def move(self):
        '''子弹移动'''
        self.y -= 10
        if self.y <= -20:
            return True

class EnemyBullet:
    '''敌机子弹类'''
    def __init__(self, screen_temp, x, y):
        self.x = x + 53
        self.y = y + 75
        self.screen = screen_temp
        self.image = pygame.image.load("./images/eshot.png")

    def display(self):
        '''绘制敌机子弹'''
        self.screen.blit(self.image,(self.x,self.y))

    def move(self):
        '''敌机子弹移动'''
        self.y += 6
        if self.y >= 568+20:
            return True

class EnemyPlane:
    '''敌机类'''
    def __init__(self, screen_temp):
        self.x = random.choice(range(408))
        self.y = -75
        self.screen = screen_temp
        self.image = pygame.image.load("./images/e"+str(random.choice(range(3)))+".png")
        self.bullet_list = []      # 用于存放敌机的子弹列表
        self.is_blasting = 0       # 用于存放是否在爆炸中状态
        
    def display(self):
        '''绘制敌机'''
        # 如果敌机爆炸完成，需要消失
        if self.is_blasting > 4:
            return True
        
        # 敌机随机发射子弹，约2秒1发
        if self.is_blasting == 0 and random.choice(range(50)) == 25:
            self.fire()

        # 绘制敌机子弹
        for eb in self.bullet_list:
            eb.display()
            if eb.move():
                self.bullet_list.remove(eb)
                
        self.screen.blit(self.image,(self.x,self.y))

        # 如果敌机正在爆炸中
        if self.is_blasting > 0:
            # 根据爆炸状态显示爆炸图片
            blasting_image = pygame.image.load("./images/blast0"+str(self.is_blasting)+".png")
            self.screen.blit(blasting_image,(self.x+36,self.y+30))
            # 进入下一个爆炸状态
            self.is_blasting += 1

        return False

    def move(self,hero):
        '''敌机向下移动'''
        # 处于非爆炸状态的敌机才移动
        if self.is_blasting == 0:
            self.y += 4
            # 敌机出屏幕，需要删除
            if self.y > 568:
                return True
            
            # 遍历所有子弹并执行碰撞检测
            for bo in hero.bullet_list:
                if bo.x > self.x+12 and bo.x < self.x+92 and bo.y > self.y+20 and bo.y < self.y+60:
                    hero.bullet_list.remove(bo)
                    # 敌机进入第一个爆炸状态，爆炸完成再删除
                    self.is_blasting = 1
                    print("Enemy Plane Be Shot...")
                    return False

        return False

    def fire(self):
        '''敌机发射子弹'''
        self.bullet_list.append(EnemyBullet(self.screen,self.x,self.y))


class HeroPlane:
    '''玩家飞机（英雄）'''
    def __init__(self, screen_temp):
        self.x = 200
        self.y = 400
        self.screen = screen_temp
        self.image = pygame.image.load("./images/me.png")
        self.bullet_list = []   #用于存放玩家的子弹列表
        self.is_blasting = 0    # 用于存放是否在爆炸中状态

    def display(self, emlist_temp):
        '''绘制玩家飞机'''

        # 如果玩家飞机爆炸完成，需要结束游戏
        if self.is_blasting > 4:
            return True

        # 绘制子弹
        for b in self.bullet_list:
            b.display()
            if b.move():
                self.bullet_list.remove(b)
                    
        self.screen.blit(self.image,(self.x,self.y))

        # 如果玩家飞机正在爆炸中
        if self.is_blasting > 0:
            # 根据爆炸状态显示爆炸图片
            blasting_image = pygame.image.load("./images/blast0"+str(self.is_blasting)+".png")
            self.screen.blit(blasting_image,(self.x+37,self.y+18))
            # 进入下一个爆炸状态
            self.is_blasting += 1
        else:
            # 判断是否玩家飞机是否被敌机子弹击中，如被击中进入第一个爆炸状态，爆炸完成再结束游戏
            if self.is_shot(emlist_temp):
                self.is_blasting = 1

        return False

    def move_left(self):
        '''左移动玩家飞机'''
        # 处于非爆炸状态的玩家飞机才移动
        if self.is_blasting == 0:
            self.x -= 5
            if self.x <= 0:
                self.x = 0

    def move_right(self):
        '''右移动玩家飞机'''
        # 处于非爆炸状态的玩家飞机才移动
        if self.is_blasting == 0:
            self.x += 5
            if self.x >= 406:
                self.x = 406

    def fire(self):
        '''玩家飞机发射子弹'''
        # 处于非爆炸状态的玩家飞机才发射子弹
        if self.is_blasting == 0:
            self.bullet_list.append(Bullet(self.screen,self.x,self.y))

    def is_shot(self, emlist_temp):
        '''玩家飞机是否被敌机子弹击中'''
        # 处于爆炸状态的玩家飞机肯定是被击中的
        if self.is_blasting > 0:
            return True
        
        # 遍历所有敌机
        for em in emlist_temp:
            # 遍历每架敌机的所有子弹
            for ebu in em.bullet_list:
                if ebu.x+1 > self.x+12 and ebu.x+1 < self.x+94 and ebu.y+17 > self.y+20 and ebu.y+17 < self.y+50:
                    em.bullet_list.remove(ebu)
                    print("Hero Plane Be Shot...")
                    return True
            
        return False
        
# 键盘控制函数
def key_control(hero_temp, enemylist_temp):
    '''键盘控制函数'''
    # 退出事件处理
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            print("exit()")
            exit()

    # 获取按键信息
    pressed_keys = pygame.key.get_pressed()
    # print(pressed_keys)
    # 做判断，并执行对象的操作
    if pressed_keys[K_LEFT] or pressed_keys[K_a]:
        print("Left...")
        hero_temp.move_left()
    elif pressed_keys[K_RIGHT] or pressed_keys[K_d]:
        print("Right...")
        hero_temp.move_right()

    if pressed_keys[K_SPACE]:
        print("Space...")
        hero_temp.fire()

def main():
    '''游戏的主程序执行函数'''
    # 创建游戏窗口，
    screen = pygame.display.set_mode((512,568),0,0)

    # 创建一个游戏背景
    background = pygame.image.load("./images/bg2.jpg")
    # 设置窗口标题
    pygame.display.set_caption("飞机大战")

    # 创建玩家飞机（英雄）
    hero = HeroPlane(screen) 
    
    m = -968
    enemylist = []      #存放敌机列表
    while True:
        # 绘制画面
        screen.blit(background, (0,m))
        m += 2
        if m >= -200:
            m = -968

        # 绘制玩家飞机。如果玩家飞机已经爆炸完成，需要结束游戏
        if hero.display(enemylist):
            # 显示"Game Over"，结束循环
            pygame.font.init()
            text_font = pygame.font.Font("./segoeprb.ttf", 48)
            text_box = text_font.render("Game Over!", True, (255,0,0))
            text_rect = text_box.get_rect()
            text_rect.center = (256, 284)
            screen.blit(text_box, text_rect)
            pygame.display.update()
            break
        
        else:
            # 执行键盘控制
            key_control(hero,enemylist)

            # 随机绘制敌机
            if random.choice(range(50)) == 10:
                enemylist.append(EnemyPlane(screen))
            # 遍历敌机并绘制移动
            for em in enemylist:
                if em.display():
                    enemylist.remove(em)
                else:
                    if em.move(hero):
                        enemylist.remove(em)
                
            # 更新显示
            pygame.display.update()

            #定时显示
            time.sleep(0.04)

    while True:
        # 退出事件处理
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                print("exit()")
                exit()


# 判断当前是否是主运行程序，并调用
if __name__ =="__main__":
    main()
